package com.jz.netthings.utils;

import com.jz.netthings.bean.JwdEntity;
import com.jz.netthings.bean.system.JyUser;
import com.jz.netthings.exception.AdscmSystemException;
import com.jz.netthings.security.utils.Token;
import com.jz.netthings.support.SecurityConstants;
import com.jz.netthings.utils.config.PropertiesUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.configurationprocessor.json.JSONArray;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.ResourceUtils;
import sun.misc.BASE64Encoder;

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.Thumbnails.Builder;

import javax.servlet.http.HttpServletRequest;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author yyy
 * @ClassName StringUtils
 * @Description 工具类
 * @date 2018/7/26 19:12
 */
public class AdscmBaseUtils {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private AdscmBaseUtils() {
    }

    private static byte[] nullNursePhoto;
    private static byte[] nullProviderPhoto;
    private static AdscmBaseUtils stringUtils;

    public static AdscmBaseUtils getInstance() {
        synchronized (AdscmBaseUtils.class) {
            if (stringUtils == null) {
                stringUtils = new AdscmBaseUtils();
                try{
                    nullNursePhoto = stringUtils.getFileBytes("D:\\adscm\\images\\nullNursePhoto.jpg");
                    nullProviderPhoto = stringUtils.getFileBytes("D:\\adscm\\images\\nullProviderPhoto.jpg");
                }catch (Exception e){}
            }
            return stringUtils;
        }
    }



    /**
     * 把一个装了Map的list中的全部值拿出来放到一个Map里面
     * @param mapList
     * @return
     */
    public Map<String, Object> getListMapToMap(List<Map<String, Object>> mapList) {

        Map<String, Object> resultMap = new HashMap<>();
        try{
            if (mapList != null && mapList.size()>0){
                for (Map<String, Object> map : mapList) {
                    Set<String> countKey = map.keySet();
                    Iterator<String> iterator = countKey.iterator();
                    while (iterator.hasNext()){
                        String yearKey = iterator.next();
                        Object yearValue = map.get(yearKey);
                        resultMap.put(yearKey,yearValue);
                    }
                }
            }
            this.sortMapByKeyNum(resultMap);
        }catch (Exception e){
            logger.error("把一个装了Map的list中的全部值拿出来放到一个Map里面异常",e);
        }
        return resultMap;
    }

    /**
     * 根据map的key排序
     * @param map
     * @return
     */
    public Map<String, Object> sortMapByKey(Map<String, Object> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }

        Map<String, Object> sortMap = new TreeMap<String, Object>(new Comparator<String>() {

            @Override
            public int compare(String o1,String o2) {

                return ((String)o1).compareTo((String) o2);
            }
        });

        sortMap.putAll(map);

        return sortMap;
    }
    /**
     * 根据map的key后面的数字序号排序（仅仅能用于key后面都有数字的）
     * @param map
     * @return
     */
    public Map<String, Object> sortMapByKeyNum(Map<String, Object> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }

        Map<String, Object> sortMap = new TreeMap<String, Object>(new Comparator<String>() {

            @Override
            public int compare(String o1,String o2) {

                String regEx = "[^0-9]";//匹配指定范围内的数字

                //Pattern是一个正则表达式经编译后的表现模式
                Pattern p = Pattern.compile(regEx);

                // 一个Matcher对象是一个状态机器，它依据Pattern对象做为匹配模式对字符串展开匹配检查。
                Matcher m1 = p.matcher(o1);
                Matcher m2 = p.matcher(o2);

                //将输入的字符串中非数字部分取代
                String s1 = m1.replaceAll("").trim();
                String s2 = m2.replaceAll("").trim();

                try{
                    return Integer.parseInt(s1) - Integer.parseInt(s2);
                }catch (Exception e){
                    logger.error("排序出错",e);
                    return 0;
                }
            }
        });

        sortMap.putAll(map);

        return sortMap;
    }


    /**
     * 根据文件地址，获取文件的二进制数据
     * @param filePath
     * @return
     * @throws AdscmSystemException
     */
    public byte[] getFileBytes(String filePath) throws AdscmSystemException{

        logger.info("获取文件【"+filePath+"】的二进制数据开始...");
        File file = new File(filePath);
        byte[] data = null;
        FileInputStream in = null;
        try{

            in = new FileInputStream(file);
            data = new byte[in.available()];
            in.read(data);

            logger.info("获取文件【"+filePath+"】的二进制数据成功...");
        }catch (Exception e){
            logger.error("获取文件【"+filePath+"】的二进制数据异常...");
            throw new AdscmSystemException("读取文件的二进制数据异常："+e.getMessage());
        }finally {
            if (in != null){
                try {
                    in.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return data;
    }


    /**
     * 获取默认没有头像的护士头像
     * @return
     */
    public byte[] getNullNursePhoto(){
        return  AdscmBaseUtils.nullNursePhoto;
    }
    /**
     * 获取默认没有头像的浆员头像
     * @return
     */
    public byte[] getNullProviderPhoto(){
        return  AdscmBaseUtils.nullProviderPhoto;
    }


    /**
     * 给原字符串加上数据库模糊匹配查询的%符号
     *
     * @param src
     * @return
     */
    public String addLikeStr(String src) {
        if (src != null && !"".equals(src.trim())) {
            src = src.replaceAll(" ", "");

            char[] chars = src.toCharArray();
            StringBuffer buffer = new StringBuffer();
            buffer.append("%");

            for (int i = 0; i < chars.length; i++) {
                buffer.append(chars[i]);
                buffer.append("%");
            }
            src = buffer.toString();
            return src;
        } else {
            return null;
        }
    }


    /**
     * 根据地址获取地址经纬度
     *
     * @param address
     * @return
     */
    public JwdEntity getJwdByAddress(String address) {
        JwdEntity jwd = null;
        try {
//            if(PropertiesUtils.tencentApiUrl == null){
//                PropertiesUtils.tencentApiUrl = "https://apis.map.qq.com/ws/geocoder/v1/";
//            }
//            if(PropertiesUtils.tencentApiKey == null){
//                PropertiesUtils.tencentApiKey = "QWMBZ-E4VC6-JMVSB-MVKIP-HKYX2-VBFGQ";
//            }

            if (address != null && !"".equals(address)) {
                StringBuffer param = new StringBuffer();
                param.append("address=" + address);
                param.append("&key=" + PropertiesUtils.tencentApiKey);
                String result = HttpRequest.sendGet(PropertiesUtils.tencentApiGeocoderUrl, param.toString());

                logger.info("地址服务器反馈信息：" + result);

                JSONObject json = new JSONObject(result);

                int status = json.getInt("status");

                if (status == 0) {
                    //成功
                    JSONObject location = json.getJSONObject("result").getJSONObject("location");

                    jwd = new JwdEntity();
                    jwd.setAddress(address);
                    jwd.setJd(location.getDouble("lng"));
                    jwd.setWd(location.getDouble("lat"));

                } else {
                    logger.warn("获取地址【" + address + "】经纬度异常，地址服务器反馈信息：" + result);
                }


            }


        } catch (Exception e) {
            logger.error("获取地址【" + address + "】经纬度异常...", e);
        }
        return jwd;
    }

    /**
     * 获取两个地址间的距离和预计行车时间（分钟）
     * @param from 起始点的坐标，经纬度中间用,隔开
     * @param to 目的地的坐标，经纬度中间用,隔开
     * @return
     */
    public Map<String,Integer> getDistance(String from ,String to) {
        Map<String,Integer> map = new HashMap<>();
        try {

            if (this.isNotEmpty(from,null) && this.isNotEmpty(to,null)) {
                StringBuffer param = new StringBuffer();
                param.append("mode=driving");
                param.append("&from="+from);
                param.append("&to="+to);
                param.append("&key=" + PropertiesUtils.tencentApiKey);
                String result = HttpRequest.sendGet(PropertiesUtils.tencentApiDistanceUrl, param.toString());

                logger.info("定位距离服务器反馈信息：" + result);

                JSONObject json = new JSONObject(result);

                int status = json.getInt("status");

                if (status == 0) {
                    //成功
                    JSONArray elements = json.getJSONObject("result").getJSONArray("elements");
                    int resultDistance = elements.getJSONObject(0).getInt("distance");
                    Long resultDuration = elements.getJSONObject(0).getLong("duration");

                    resultDistance = Math.round(resultDistance / 1000f);
                    map.put("distance",resultDistance);
                    map.put("duration",Math.round(resultDuration / 60f));
                } else {
                    logger.warn("获取距离【" + from + " ： "+ to +"】异常，地址服务器反馈信息：" + result);
                }
            }
        } catch (Exception e) {
            logger.error("获取距离【" + from + " ： "+ to +"】异常...", e);
        }
        return map;
    }

    /**
     * 在指定的字符串前拼装 指定字符串
     *
     * @param source            ：指定字符串
     * @param len：拼装出来的总长度
     * @param addStr：需要拼装的指定字符串
     * @return
     */
    public String addZeroToStr(String source, int len, String addStr) {

        StringBuffer buffer = new StringBuffer();
        if (source == null) {
            source = "";
        }

        for (int i = 0; source != null && buffer.length() < (len - source.length()); i++) {
            buffer.append(addStr);
        }

        buffer.append(source);

        return buffer.toString();
    }

    /**
     * 判断一个对象是否为空，如果指定了某个属性，则即使对象不为空，这个对象的这个属性为空，则也返回 true
     * 如果没有指定field属性，则判断对象是否为空
     *
     * @param source
     * @param field
     * @return
     */
    public boolean isNotEmpty(Object source, String field) {
        if (source == null || "".equals(source)) {
            return false;
        } else {
            if (field == null || "".equals(field)) {
                return true;//如果传入的属性值为null，则直接返回对象是否为空
            } else {
                Class clazz = source.getClass();
                try {
                    Field field_ = clazz.getDeclaredField(field);
                    field_.setAccessible(true); // 设置属性是可以访问的(私有的也可以)

                    Object obj = field_.get(source);
                    if (obj == null || "".equals(obj)) {
                        return false;
                    } else {
                        return true;
                    }

                } catch (NoSuchFieldException e) {
                    logger.error("对象Object[" + source + "]没有属性[" + field + "],StringUtils.isEmpty()方法返回true...", e);
                    return false;
                } catch (IllegalAccessException e) {
                    logger.error("获取对象Object[" + source + "]的属性[" + field + "]异常,StringUtils.isEmpty()方法返回true...", e);
                    e.printStackTrace();
                    return false;
                }
            }

        }
    }

    /**
     * 判断一个list是否为null
     * @param list
     * @return
     */
    public boolean listIsNotEmpty(List<?> list) {
        boolean flag = false;
        if (list != null && list.size()>0){
            flag = true;
        }
        return  flag;
    }

    /**
     * 获取请求的IP
     *
     * @param request
     * @return
     */
    public String getIPAddress(HttpServletRequest request) {
        // 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址

        String ip = request.getHeader("X-Forwarded-For");

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
            if ("0:0:0:0:0:0:0:1".equals(ip)) {
                ip = "127.0.0.1";
            }
        } else if (ip.length() > 15) {
            String[] ips = ip.split(",");
            for (int index = 0; index < ips.length; index++) {
                String strIp = (String) ips[index];
                if (!("unknown".equalsIgnoreCase(strIp))) {
                    ip = strIp;
                    break;
                }
            }
        }
        return ip;
    }


    /**
     * 根据tokenID，获取Redis中的token
     *
     * @param tokenId
     * @param tokenRedisTemplate
     * @return
     */
    public Token getTokenByTokenId(String tokenId, RedisTemplate<Object, Token> tokenRedisTemplate) {
        synchronized (this) {
            if (AdscmBaseUtils.getInstance().isNotEmpty(tokenId, null)) {
                logger.info("根据tokenId[" + tokenId + "]获取Redis中的Token信息...");

                ValueOperations<Object, Token> vo = tokenRedisTemplate.opsForValue();
                Token token = vo.get(tokenId);

                return token;

            } else {
                return null;
            }
        }
    }

    public void cleanToken(String tokenId, RedisTemplate<Object, Token> tokenRedisTemplate) throws AdscmSystemException {
        try {
            synchronized (this) {
                if (AdscmBaseUtils.getInstance().isNotEmpty(tokenId, null)) {
                    logger.info("清除tokenId[" + tokenId + "]在Redis中的Token信息...");

                    ValueOperations<Object, Token> vo = tokenRedisTemplate.opsForValue();
                    Token token = vo.get(tokenId);
                    if (token != null) {
                        JyUser user = token.getUser();

                        tokenRedisTemplate.expire(tokenId, 1, TimeUnit.SECONDS);//设置过期时间
                        tokenRedisTemplate.expire(user.getUsername(), 1, TimeUnit.MILLISECONDS);//设置过期时间
                    }

                }
            }
        } catch (Exception e) {
            throw new AdscmSystemException("清除token异常 : " + e.getMessage());
        }
    }

    /**
     * 更新token的过期时间，每个用户的每次访问，都更新他的过期时间为默认的过期时间，让他在操作的时候，永远保持在线状态
     *
     * @param tokenId
     * @param tokenRedisTemplate
     * @throws AdscmSystemException
     */
    public void updateTokenTimeOut(String tokenId, RedisTemplate<Object, Token> tokenRedisTemplate) throws AdscmSystemException {
        try {
            synchronized (this) {
                if (AdscmBaseUtils.getInstance().isNotEmpty(tokenId, null)) {

                    ValueOperations<Object, Token> vo = tokenRedisTemplate.opsForValue();
                    Token token = vo.get(tokenId);
                    if (token != null) {
                        JyUser user = token.getUser();

                        //设置过期时间
                        tokenRedisTemplate.expire(user.getUsername(), SecurityConstants.DEFAULT_SIGN_EXPIRE_TIME, TimeUnit.MINUTES);
                        tokenRedisTemplate.expire(token.getTokenId(), SecurityConstants.DEFAULT_SIGN_EXPIRE_TIME, TimeUnit.MINUTES);
                    }

                }
            }
        } catch (Exception e) {
            throw new AdscmSystemException("更新token的过期时间异常 : " + e.getMessage());
        }
    }

    /**
     * 将对象存放到Redis中
     *
     * @param key
     * @param obj
     * @param objectRedisTemplate
     */
    public void addObjToRedis(String key, Object obj, RedisTemplate<Object, Object> objectRedisTemplate) {
        synchronized (this) {
            if (AdscmBaseUtils.getInstance().isNotEmpty(obj, null)) {

                logger.info("将对象放到Redis中...");

                ValueOperations<Object, Object> vo = objectRedisTemplate.opsForValue();

                Object ko = vo.get(key);
                if (ko == null) {
                    vo.set(key, obj);
                }
                objectRedisTemplate.expire(key, 900, TimeUnit.MINUTES);
            }

        }
    }

    /**
     * 将对象存放到Redis中，手动设置过期时间
     * @param key
     * @param obj
     * @param objectRedisTemplate
     * @param overdueTime 过期时间
     * @param overdueTimeType 过期时间类型
     */
    public void addObjToRedis(String key, Object obj, RedisTemplate<Object, Object> objectRedisTemplate,int overdueTime,TimeUnit overdueTimeType) {
        try{
            synchronized (this) {
                if (AdscmBaseUtils.getInstance().isNotEmpty(obj, null)) {

                    logger.info("将对象放到Redis中...");

                    ValueOperations<Object, Object> vo = objectRedisTemplate.opsForValue();

                    Object ko = vo.get(key);
                    if (ko == null) {
                        vo.set(key, obj);
                    }
//                objectRedisTemplate.expire(key, 900, TimeUnit.MINUTES);
                    objectRedisTemplate.expire(key, overdueTime,overdueTimeType);
                }

            }
        }catch (Exception e){
            logger.error("把对象【"+obj.getClass()+"】存入Redis异常",e);
        }

    }

    /**
     * 将对象从Redis中移除
     *
     * @param key
     * @param objectRedisTemplate
     */
    public void cleanObjFromRedis(String key, RedisTemplate<Object, Object> objectRedisTemplate) throws AdscmSystemException {
        try {
            synchronized (this) {
                if (AdscmBaseUtils.getInstance().isNotEmpty(key, null)) {
                    logger.info("清除[" + key + "]在Redis中的信息...");

                    ValueOperations<Object, Object> vo = objectRedisTemplate.opsForValue();
                    Object o = vo.get(key);
                    if (o != null) {
                        objectRedisTemplate.expire(key, 1, TimeUnit.SECONDS);//设置过期时间
                    }

                }
            }
        } catch (Exception e) {
            throw new AdscmSystemException("清除数据异常 : " + e.getMessage());
        }
    }

//    /**
//     * 保存对象到 Redis 的 List 集合中
//     * @param listKey 保存list的key
//     * @param obj 待保存的对象
//     * @param redisTemplate
//     */
//    public void saveObjToRedisList(String listKey,Object obj,RedisTemplate<String,List<Object>> redisTemplate){
//        try {
//            synchronized (this){
//                List<Object> list = redisTemplate.opsForList().leftPop(listKey);
//
//                if (list != null && list.size()>0){
//
//                }else {
//                    list = new ArrayList<>();
//                }
//                list.add(obj);
//                redisTemplate.opsForList().leftPush(listKey,list);
//            }
//
//        }catch (Exception e){
//            logger.error("保存对象到Redis 的 list  中出现异常  " , e);
//        }
//    }


    public String readImgToBase64(String filePath) {

        String base64 = "";
        try {
            InputStream inputStream = null;
            byte[] data = null;
            try {
                inputStream = new FileInputStream(filePath);
                data = new byte[inputStream.available()];
                inputStream.read(data);
                inputStream.close();
            } catch (IOException e) {
                logger.error("读取文件【" + filePath + "】异常", e);
            }
            // 加密
            BASE64Encoder encoder = new BASE64Encoder();
            if (data != null) {
                base64 = encoder.encode(data);
            }

        } catch (Exception e) {
            logger.error("文件【" + filePath + "】转换成Base64字符串异常", e);
        }
        return base64;

    }

    /**
     * 求一个数的相反数
     *
     * @param num
     * @return
     */
    public int getOppositeNum(Integer num) {
        if (num == null) {
            num = 0;
        }
        return (num * -1);
    }


    /**
     * 复制单个文件
     *
     * @param oldPath String  原文件路径  如：c:/fqf.txt
     * @param newPath String  复制后路径  如：f:/fqf.txt
     * @return boolean
     */
    public void copyFile(String oldPath, String newPath) {
        try {
//           int  bytesum  =  0;
            int byteread = 0;
            File oldfile = new File(oldPath);
            if (oldfile.exists()) {  //文件存在时
                InputStream inStream = new FileInputStream(oldPath);  //读入原文件
                FileOutputStream fs = new FileOutputStream(newPath);
                byte[] buffer = new byte[1444];
//               int  length;
                while ((byteread = inStream.read(buffer)) != -1) {
//                   bytesum  +=  byteread;  //字节数  文件大小
//                   System.out.println(bytesum);
                    fs.write(buffer, 0, byteread);
                }
                inStream.close();
            }
        } catch (Exception e) {
            System.out.println("复制单个文件操作出错");
            e.printStackTrace();

        }

    }


    /**
     * 删除文件
     *
     * @param filePathAndName String  文件路径及名称  如c:/fqf.txt
     * @return boolean
     */
    public void delFile(String filePathAndName) {
        try {
            String filePath = filePathAndName;
            filePath = filePath.toString();
            java.io.File myDelFile = new java.io.File(filePath);
            myDelFile.delete();

        } catch (Exception e) {
            System.out.println("删除文件操作出错");
            e.printStackTrace();

        }

    }

    /**
     * 移动文件到指定目录
     *
     * @param oldPath String  如：c:/fqf.txt
     * @param newPath String  如：d:/fqf.txt
     */
    public void moveFile(String oldPath, String newPath) {
        copyFile(oldPath, newPath);
        delFile(oldPath);

    }



    /**
     * 获取这个对象的属性值
     *
     * @param obj
     * @return
     */
    public String getFieldsInfo(Object obj, Class cls) {
        StringBuffer sb = new StringBuffer();
        try {

            Field[] declaredFields = cls.getDeclaredFields();
            for (Field field : declaredFields) {
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), cls);
                Method getMethod = pd.getReadMethod();
                Object o1 = getMethod.invoke(obj);
                String s1 = o1 == null ? "" : o1.toString();
                sb.append(s1 + " ");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    /**
     * 同一对象有哪些值是不同的
     *
     * @param newobj
     * @param oldobj
     * @return
     */
    public String compareObj(Object newobj, Object oldobj, Class cls) {
        StringBuffer sb = new StringBuffer();
        try {
            Field[] declaredFields = cls.getDeclaredFields();
            for (Field field : declaredFields) {
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), cls);
                Method getMethod = pd.getReadMethod();
                Object o1 = getMethod.invoke(newobj);
                Object o2 = getMethod.invoke(oldobj);

                String s1 = o1 == null ? "" : o1.toString();
                String s2 = o2 == null ? "" : o2.toString();

                if (!s1.equals(s2)) {
                    sb.append(s2 + " 修改为 " + s1);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }


    /**
     * 查询用户
     *
     * @param tokenId
     * @param tokenRedisTemplate
     * @return
     */
    public JyUser getUser(String tokenId, RedisTemplate<Object, Token> tokenRedisTemplate) {

        JyUser user = null;
        if (tokenId != null && !"".equals(tokenId) && tokenRedisTemplate != null) {
            Token token = this.getTokenByTokenId(tokenId, tokenRedisTemplate);
            if (token != null) {
                user = token.getUser();
            }
        }
        return user;
    }


    private int compare(String str, String target) {
        int d[][];              // 矩阵
        int n = str.length();
        int m = target.length();
        int i;                  // 遍历str的
        int j;                  // 遍历target的
        char ch1;               // str的
        char ch2;               // target的
        int temp;               // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
        if (n == 0) {
            return m;
        }
        if (m == 0) {
            return n;
        }
        d = new int[n + 1][m + 1];
        for (i = 0; i <= n; i++) {                       // 初始化第一列
            d[i][0] = i;
        }

        for (j = 0; j <= m; j++) {                       // 初始化第一行
            d[0][j] = j;
        }

        for (i = 1; i <= n; i++) {                       // 遍历str
            ch1 = str.charAt(i - 1);
            // 去匹配target
            for (j = 1; j <= m; j++) {
                ch2 = target.charAt(j - 1);
                if (ch1 == ch2 || ch1 == ch2 + 32 || ch1 + 32 == ch2) {
                    temp = 0;
                } else {
                    temp = 1;
                }
                // 左边+1,上边+1, 左上角+temp取最小
                d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + temp);
            }
        }
        return d[n][m];
    }

    private int min(int one, int two, int three) {
        return (one = one < two ? one : two) < three ? one : three;
    }

    /**
     * 获取两字符串的相似度
     *
     * @param str
     * @param target
     * @return
     */
    public float getSimilarityRatio(String str, String target) {
        return 1 - (float) compare(str, target) / Math.max(str.length(), target.length());
    }


//    public static void main(String[] args)
//    {
////        String str = "四川省";
////        String target = "四川省";
////        System.out.println("similarityRatio=" + AdscmBaseUtils.getInstance().getSimilarityRatio(str, target));
//
//        StringBuffer names = new StringBuffer();
//        names.append("张三、李四、王二麻子、");
//        ;
//        System.out.println();
//
//    }


    /**
     * 压缩图片格式
     *
     * @param value
     * @param width
     * @param height
     * @return
     */
    public byte[] buildIcon(byte[] value, int width, int height) {
        try {
            if (value != null) {
                if (value.length > 0) {
                    try {
                        java.io.ByteArrayInputStream bin = new java.io.ByteArrayInputStream(value);
                        try {
                            java.io.DataInputStream in = new java.io.DataInputStream(bin);
                            try {
                                Builder<? extends InputStream> imagebuild = Thumbnails.of(in);
                                try {
                                    imagebuild.size(width, height);
                                    imagebuild.outputFormat("jpeg");
                                    java.io.ByteArrayOutputStream os = new java.io.ByteArrayOutputStream();
                                    try {
                                        imagebuild.toOutputStream(os);
                                        value = os.toByteArray();
                                    } finally {
                                        os.close();
                                    }
                                    return value;
                                } finally {
                                    imagebuild = null;
                                }
                            } finally {
                                in.close();
                            }
                        } finally {
                            bin.close();
                        }
                    } finally {
                        value = null;
                    }
                }
            }
        } catch (java.lang.Exception e) {
            logger.error("压缩图片异常",e);
        }
        return null;
    }


    /**
     * 获取上传路径
     *
     * @return
     */
    public String getUploadpath() {

        File classpath = null;
        try {
            classpath = new File(ResourceUtils.getURL("classpath:").getPath());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        String gitPath = classpath.getParentFile().getParentFile().getParent() + File.separator + "adscm" + File.separator + "uploads" + File.separator;
        return gitPath;
    }
//
//    public static void main(String[] args) throws  Exception {
//
//        JwdEntity jwdByAddress = AdscmBaseUtils.getInstance().getJwdByAddress("甘肃省定西市临潭县");
////        Map<String ,Integer> map = AdscmBaseUtils.getInstance().getDistance("33.89733100,104.02346000","34.4421300000,104.0541300000");
//
//        System.out.println(jwdByAddress);
//    }

    /**
     * 根据当前页和每页行数，得到从数据库分页查询的起始位置
     * @param current
     * @param size
     * @return
     */
    public Integer getCurrentStartIdx(Integer current,Integer size){
        if (current == null){
            current = 1;
        }
        if (size == null){
            current = 10;
        }

        if (current!=0){
            if (current==1){
                current=0;
            }else {
                current=((current-1)*size)/*-1*/;
            }
        }

        return current;
    }


    /**
     * 写文件到本地磁盘
     * @param fileBytes
     * @param targetPath
     * @throws Exception
     */
    public void writeFileToDisk(byte[] fileBytes,String targetPath) throws  Exception{

        if (!AdscmBaseUtils.getInstance().isNotEmpty(targetPath,null)){
            throw  new AdscmSystemException("文件路径为Null，写入磁盘失败...");
        }

        int i = targetPath.lastIndexOf("\\");
        if (i<0){
            i = targetPath.lastIndexOf("/");
        }
        String str = targetPath.substring(0, i);
        System.out.println(str);
        File targetFile = new File(str);

        FileOutputStream fos = null;
        try {
            if (!targetFile.exists()){
                targetFile.mkdirs();
            }
            targetFile = new File(targetPath);

            fos = new FileOutputStream(targetFile);

            fos.write(fileBytes);
            logger.info("写入文件到本地成功，文件路径【"+targetPath+"】");
        } catch (Exception e) {
            logger.error("写入文件到本地失败",e);
            throw  e;
        }finally{
            if(fos != null){
                fos.flush();
                fos.close();
            }
        }
    }

    /**
     * 根据民族查询对应的编号
     * @param nation
     * @return
     */
    public int getNationNO(String nation){
        int i = 1;
        if("汉".equals(nation)){ i = 1;
        }else if("蒙古".equals(nation)){ i = 2;
        }else if("回".equals(nation)){ i = 3;
        }else if("藏".equals(nation)){ i = 4;
        }else if("维吾尔".equals(nation)){ i = 5;
        }else if("苗".equals(nation)){ i = 6;
        }else if("彝".equals(nation)){ i = 7;
        }else if("壮".equals(nation)){ i = 8;
        }else if("布依".equals(nation)){ i = 9;
        }else if("朝鲜".equals(nation)){ i = 10;
        }else if("满".equals(nation)){ i = 11;
        }else if("侗".equals(nation)){ i = 12;
        }else if("瑶".equals(nation)){ i = 13;
        }else if("白".equals(nation)){ i = 14;
        }else if("土家".equals(nation)){ i = 15;
        }else if("哈尼".equals(nation)){ i = 16;
        }else if("哈萨克".equals(nation)){ i = 17;
        }else if("傣".equals(nation)){ i = 18;
        }else if("黎".equals(nation)){ i = 19;
        }else if("傈僳".equals(nation)){ i = 20;
        }else if("佤".equals(nation)){ i = 21;
        }else if("畲".equals(nation)){ i = 22;
        }else if("高山".equals(nation)){ i = 23;
        }else if("拉祜".equals(nation)){ i = 24;
        }else if("水".equals(nation)){ i = 25;
        }else if("东乡".equals(nation)){ i = 26;
        }else if("纳西".equals(nation)){ i = 27;
        }else if("景颇".equals(nation)){ i = 28;
        }else if("柯尔克孜".equals(nation)){ i = 29;
        }else if("土".equals(nation)){ i = 30;
        }else if("达斡尔".equals(nation)){ i = 31;
        }else if("仫佬".equals(nation)){ i = 32;
        }else if("羌".equals(nation)){ i = 33;
        }else if("布朗".equals(nation)){ i = 34;
        }else if("撒拉".equals(nation)){ i = 35;
        }else if("毛难".equals(nation)){ i = 36;
        }else if("仡佬".equals(nation)){ i = 37;
        }else if("锡伯".equals(nation)){ i = 38;
        }else if("阿昌".equals(nation)){ i = 39;
        }else if("普米".equals(nation)){ i = 40;
        }else if("塔吉克".equals(nation)){ i = 41;
        }else if("怒".equals(nation)){ i = 42;
        }else if("乌孜别克".equals(nation)){ i = 43;
        }else if("俄罗斯".equals(nation)){ i = 44;
        }else if("鄂温克".equals(nation)){ i = 45;
        }else if("德昂".equals(nation)){ i = 46;
        }else if("保安".equals(nation)){ i = 47;
        }else if("裕固".equals(nation)){ i = 48;
        }else if("京".equals(nation)){ i = 49;
        }else if("塔塔尔".equals(nation)){ i = 50;
        }else if("独龙".equals(nation)){ i = 51;
        }else if("鄂伦春".equals(nation)){ i = 52;
        }else if("赫哲".equals(nation)){ i = 53;
        }else if("门巴".equals(nation)){ i = 54;
        }else if("珞巴".equals(nation)){ i = 55;
        }else if("基诺".equals(nation)){ i = 56;
        }
        return i;
    }

    /**
     * 根据民族id获取名字
     * @param i
     * @return
     */
    public  String getNation(int i){
        String nation="汉";
        if (i==1){ nation="汉";
        }else if(i==2){ nation = "蒙古";
        }else if(i ==3){ nation ="回";
        }else if(i == 4){ nation ="藏";
        }else if(i ==5 ){ nation="维吾尔";
        }else if( i == 6){nation="苗";
        }else if( i ==7){;nation="彝";
        }else if(i ==8){ nation="壮";
        }else if(i == 9){nation= "布依";
        }else if( i ==10){nation="朝鲜";
        }else if(i == 11){ nation="满";
        }else if(i == 12){ nation="侗";
        }else if( i == 13){nation="瑶";
        }else if( i ==14){nation="白";
        }else if(i == 15){nation="土家" ;
        }else if(i == 16){nation="哈尼" ;
        }else if(i == 17){nation="哈萨克" ;
        }else if(i == 18){nation="傣" ;
        }else if(i == 19){ nation="黎";
        }else if(i ==20){ nation="傈僳";
        }else if(i == 21){ nation="佤";
        }else if(i == 22){nation="畲" ;
        }else if(i == 23){nation="高山";
        }else if(i == 24){ nation="拉祜";
        }else if(i == 25){nation="水" ;
        }else if(i == 26){nation="东乡" ;
        }else if(i == 27){nation="纳西" ;
        }else if(i == 28){nation="景颇" ;
        }else if(i == 29){nation="柯尔克孜" ;
        }else if(i == 30){ nation="土";
        }else if(i == 31){nation="达斡尔" ;
        }else if(i == 32){nation= "仫佬";
        }else if(i == 33){ nation="羌";
        }else if(i ==34){nation="布朗" ;
        }else if(i ==35){ nation="撒拉";
        }else if(i == 36){nation="毛难" ;
        }else if(i == 37){nation="仡佬" ;
        }else if(i == 38){nation="锡伯" ;
        }else if(i == 39){nation= "阿昌";
        }else if(i == 40){ nation="普米";
        }else if(i == 41){nation="塔吉克" ;
        }else if(i == 42){nation= "怒";
        }else if(i == 43){ nation="乌孜别克";
        }else if(i == 44){ nation="俄罗斯";
        }else if(i == 45){nation="鄂温克" ;
        }else if(i == 46){nation="德昂" ;
        }else if(i == 47){nation="保安";
        }else if(i == 48){ nation="裕固";
        }else if(i==49){ nation="京";
        }else if(i == 50){nation="塔塔尔" ;
        }else if(i == 51){ nation="独龙";
        }else if( i == 52){nation="鄂伦春";
        }else if(i == 53){ nation="赫哲";
        }else if( i == 54){nation="门巴";
        }else if( i == 55){nation="珞巴";
        }else if(i == 56){nation="基诺" ;
        }
        return nation;
    }

    public static void main(String[] args) {
        List<Long> list1 = new ArrayList<>();
        List<Long> list2 = new ArrayList<>();

        list1.add(1L);
        list1.add(2L);
        list1.add(3L);

        list2.add(3L);

        List<Long> list3 = (List<Long>) AdscmBaseUtils.getInstance().retainList(list1,list2);
        System.out.println(list3);
        System.out.println(AdscmBaseUtils.getInstance().removeList(list1,list2));

    }

    /**
     * 获取两个集合的交集
     */
    public  List<?> retainList(List<?> list1,List<?> list2){
        List<?> list = new ArrayList<>(list1);

        list.retainAll(list2);

//		if(list1 != null && list1.size()>0 && list2 != null && list2.size()>0){
//			for(String var : list1){
//				for(String var1 : list2){
//					if(var.equals(var1)){
//						list.add(var);
//						break;
//					}
//				}
//			}
//		}
//
        return list;

    }
    /**
     * 获取两个集合的差集
     */
    public  List<?> removeList(List<?> list1,List<?> list2){
        List<?> list = new ArrayList<>(list1);

        list.removeAll(list2);

//		if(list1 != null && list1.size()>0 && list2 != null && list2.size()>0){
//			for(String var : list1){
//				for(String var1 : list2){
//					if(var.equals(var1)){
//						list.add(var);
//						break;
//					}
//				}
//			}
//		}
//
        return list;

    }
}
